package com.xiaoshuidi.cloud.module.contract.controller.admin.roommate;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.module.contract.controller.admin.contract.vo.company.CompanyRoomListExcelVO;
import com.xiaoshuidi.cloud.module.contract.controller.admin.roommate.vo.*;
import com.xiaoshuidi.cloud.module.contract.convert.roommeta.ContractRoommateConvert;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.roommeta.ContractRoommateDO;
import com.xiaoshuidi.cloud.module.contract.enums.ApiConstants;
import com.xiaoshuidi.cloud.module.contract.listener.RoommateUploadListener;
import com.xiaoshuidi.cloud.module.contract.service.contract.ContractRoomService;
import com.xiaoshuidi.cloud.module.contract.service.roommate.ContractRoommateService;
import com.xiaoshuidi.cloud.module.system.api.dict.DictDataApi;
import com.xiaoshuidi.cloud.module.system.api.dict.dto.DictDataRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

import static com.xiaoshuidi.cloud.framework.common.pojo.CommonResult.success;


@Tag(name = "管理后台 - 合同同住人数据")
@RestController
@RequestMapping(ApiConstants.NAME + "/roommate")
@Validated
@Slf4j
public class ContractRoommateController {

    @Resource
    private ContractRoommateService roommateService;

    @Resource
    private ContractRoomService roomService;

    @Resource
    private DictDataApi dictDataApi;

    @PostMapping("/create")
    @Operation(summary = "创建合同同住人数据")
//    @PreAuthorize("@ss.hasPermission('contract:roommate:create')")
    public CommonResult<Long> createRoommate(@Valid @RequestBody ContractRoommateCreateReqVO createReqVO) {
        return success(roommateService.createRoommate(createReqVO));
    }

    @PostMapping("/update")
    @Operation(summary = "更新合同同住人数据")
//    @PreAuthorize("@ss.hasPermission('contract:roommate:update')")
    public CommonResult<Boolean> updateRoommate(@Valid @RequestBody ContractRoommateUpdateReqVO updateReqVO) {
        roommateService.updateRoommate(updateReqVO);
        return success(true);
    }

    @PostMapping("/delete")
    @Operation(summary = "删除合同同住人数据")
    @Parameter(name = "id", description = "编号", required = true)
//    @PreAuthorize("@ss.hasPermission('contract:roommate:delete')")
    public CommonResult<Boolean> deleteRoommate(@RequestParam("id") Long id) {
        roommateService.deleteRoommate(id);
        return success(true);
    }

    /**
     * 根据id获取同住人信息
     *
     * @param id
     * @return
     */
    @GetMapping("/get")
    @Operation(summary = "获得合同同住人数据")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
//    @PreAuthorize("@ss.hasPermission('contract:roommate:query')")
    public CommonResult<ContractRoommateRespVO> getRoommate(@RequestParam("id") Long id) {
        return success(roommateService.getRoommate(id));
    }

    /**
     * 根据合同id查看同住人
     *
     * @param contractId 合同id
     * @return
     */
    @GetMapping("/get-by-contract")
    @Operation(summary = "根据合同id查看同住人")
    @Parameter(name = "id", description = "合同id", required = true, example = "1024")
//    @PreAuthorize("@ss.hasPermission('contract:roommate:query')")
    public CommonResult<List<ContractRoommateListReqVO>> getByContract(@RequestParam("contractId") Long contractId) {
        List<ContractRoommateListReqVO> reqVOS = roommateService.getContractRoommateList(contractId);
        return success(reqVOS);
    }

    /**
     * 同住人退房
     *
     * @param id 合同id
     * @return
     */
    @GetMapping("/checkout")
    @Operation(summary = "同住人退房")
    @Parameter(name = "id", description = "合同id", required = true, example = "1024")
//    @PreAuthorize("@ss.hasPermission('contract:roommate:query')")
    public CommonResult<Boolean> roommateCheckout(@RequestParam("id") Long id) {
        roommateService.roommateCheckout(id);
        return success(true);
    }

    /**
     * 公司同住人退房
     *
     * @param id 合同id
     * @return
     */
    @GetMapping("/checkout-company")
    @Operation(summary = "同住人退房")
    @Parameter(name = "id", description = "同住人主键id", required = true)
    @Parameter(name = "isOne", description = "是否是主住人", required = true)
//    @PreAuthorize("@ss.hasPermission('contract:roommate:query')")
    public CommonResult<Boolean> roommateCheckoutCompany(@RequestParam("id") Long id, @RequestParam("isOne") Boolean isOne) {
        roommateService.roommateCheckoutCompany(id, isOne);
        return success(true);
    }

    @GetMapping("/list")
    @Operation(summary = "获得合同同住人数据列表")
//    @PreAuthorize("@ss.hasPermission('contract:roommate:query')")
    public CommonResult<List<ContractRoommateRespVO>> getRoommateList(@RequestParam("id") Long id) {
        List<ContractRoommateDO> list = roommateService.getRoommateList(id);
        return success(ContractRoommateConvert.INSTANCE.convertList(list));
    }

    /**
     * 获得合同同住人数据分页列表
     *
     * @param pageReqVO
     * @return
     */
    @GetMapping("/page")
    @Operation(summary = "获得合同同住人数据分页列表")
//    @PreAuthorize("@ss.hasPermission('contract:roommate:query')")
    public CommonResult<PageResult<ContractRoommatePageRespVO>> getRoommatePage(@Valid ContractRoommatePageReqVO pageReqVO) {
        PageResult<ContractRoommatePageRespVO> data = roommateService.getRoommateListPage(pageReqVO);
        return success(data);
    }

    /**
     * 房间是否超过一人
     *
     * @param id
     * @return
     */
    @GetMapping("/only-one")
    @Operation(summary = "获得合同同住人数据分页列表")
//    @PreAuthorize("@ss.hasPermission('contract:roommate:query')")
    public CommonResult<Boolean> getOnlyOne(@RequestParam("id") Long id) {
        return success(roommateService.getOnlyOne(id));
    }

    /**
     * 批量迁出
     *
     * @param ids
     * @return
     */
    @GetMapping("/emigration")
    @Operation(summary = "批量迁出")
//    @PreAuthorize("@ss.hasPermission('contract:roommate:query')")
    public CommonResult<Boolean> getRoommateEmigration(@RequestParam("ids") Collection<Long> ids) {
        roommateService.getRoommateEmigration(ids);
        return success(true);
    }

    /**
     * 设置寝室长
     *
     * @param id
     * @return
     */
    @GetMapping("/change-roommate-type")
    @Operation(summary = "设置寝室长")
//    @PreAuthorize("@ss.hasPermission('contract:roommate:query')")
    public CommonResult<Boolean> changeRoommateType(@RequestParam("id") Long id) {
        roommateService.changeRoommateType(id);
        return success(true);
    }


    @GetMapping("/get-import-template")
    @Operation(summary = "获得导入企业同住人模板")
    public void importTemplate(HttpServletResponse response, Long customerCompanyId) throws IOException {
        List<ContractRoommateImportExcelVO> list = Arrays.asList(
                ContractRoommateImportExcelVO.builder().roomId(16648881691L)
                        .fullRoomName("测试公寓001818楼808e")
                        .roommateName("胡图图").roommatePhone("18812345678")
                        .roommateIdType(1).roommateIdNumber("41270211111111").nationality("中国")
                        .roommateAge(5).roommateGender(0)
                        .roommateEducation("小学")
                        .roommatePosition("无")
                        .roommateType(0)
                        .relation("父子").build(),
                ContractRoommateImportExcelVO.builder().roomId(16648881691L)
                        .fullRoomName("测试公寓001818楼808e")
                        .roommateName("胡英俊").roommatePhone("18812345678")
                        .roommateIdType(1).roommateIdNumber("41270211111111").nationality("中国")
                        .roommateAge(30).roommateGender(0)
                        .roommateEducation("大学本科")
                        .roommatePosition("总经理")
                        .roommateType(1)
                        .relation("父子").build()
        );
        //ExcelUtils.write(response, "企业同住人.xls", "同住人信息", ContractRoommateImportExcelVO.class, list);
        // 输出 Excel
        ExcelWriter w = EasyExcel.write(response.getOutputStream())
                .autoCloseStream(false) // 不要自动关闭，交给 Servlet 自己处理
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build(); // 基于 column 长度，自动适配。最大 255 宽度
        WriteSheet sheet = EasyExcel.writerSheet("同住人信息").head(ContractRoommateImportExcelVO.class).build();
        w.write(list, sheet);

        //附带信息==房间全称，房间id
        List<CompanyRoomListExcelVO> companyRoomListExcelVOS = roomService.selectByCustomerCompanyId(customerCompanyId);
        WriteSheet sheet2 = EasyExcel.writerSheet("房间对应信息").head(Arrays.asList(Collections.singletonList("房间编号"),
                Collections.singletonList("房源"))).build();
        if (CollectionUtils.isNotEmpty(companyRoomListExcelVOS)) {
            w.write(companyRoomListExcelVOS.stream().map(c -> Arrays.asList(c.getRoomId().toString(), c.getFullRoomName())).collect(Collectors.toList()), sheet2);
        } else {
            w.write(Arrays.asList("没有正在生效中的房间", "没有正在生效中的房间"), sheet2);
        }

        //附带信息--证件类型列表
        CommonResult<List<DictDataRespDTO>> personalDocuments = dictDataApi.getDictDataByType("personalDocuments");
        if (CollectionUtils.isNotEmpty(personalDocuments.getData())) {
            WriteSheet sheet3 = EasyExcel.writerSheet("身份证类型").head(Collections.singletonList(Collections.singletonList("身份证类型"))).build();
            w.write(personalDocuments.getData().stream().map(a -> Collections.singletonList(a.getLabel())).collect(Collectors.toList()), sheet3);
        }

        // 设置 header 和 contentType。写在最后的原因是，避免报错时，响应 contentType 已经被修改了
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("企业同住人导入模板.xls", "UTF-8"));
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        w.finish();
    }

    @PostMapping("/import")
    @Operation(summary = "导入用户")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
            @Parameter(name = "updateSupport", description = "是否支持更新，默认为 false", example = "true")
    })
    //@PreAuthorize("@ss.hasPermission('system:user:import')")
    public CommonResult<ContractRoommateImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
                                                                  @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
        List<ContractRoommateImportExcelVO> list =
                EasyExcel.read(file.getInputStream(), ContractRoommateImportExcelVO.class,
                                new RoommateUploadListener<ContractRoommateImportExcelVO>())
                        .autoCloseStream(false)
                        .sheet(0).doReadSync();
        return success(roommateService.importRoommateList(list,updateSupport));
    }

    /**
     * 同住人迁入迁出数据分页列表
     *
     * @param pageReqVO
     * @return
     */
    @GetMapping("/page-logs")
    @Operation(summary = "同住人迁入迁出数据分页列表")
//    @PreAuthorize("@ss.hasPermission('contract:roommate:query')")
    public CommonResult<PageResult<ContractRoommateLogListVO>> getRoommateLogsPage(@Valid ContractRoommateLogPageReqVO pageReqVO) {
        PageResult<ContractRoommateLogListVO> data = roommateService.getRoommateLogListPage(pageReqVO);
        return success(data);
    }
}
